package coroutines

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.channels.produce

fun main(){
    runBlocking {
        val channel = Channel<Int>()
        launch {
            for (x in 1..5){
                channel.send(x * x)
            }
            channel.close()
        }
        for (y in channel){
            println("channel value print until closed $y")
        }
//        repeat(5){
//            println("channel value = ${channel.receive()}")
//        }
        println("Done")

        produceInt(3).consumeEach {
            println("produce value ==> ${it}")
        }

        val numbers = produceNumbers()
        val squares = square(numbers)
        repeat(5){
            println("take 5 ${squares.receive()}")
        }
        println("Done")
        coroutineContext.cancelChildren()
    }
}

fun CoroutineScope.produceInt(count : Int) = produce(capacity = count) {
    send(10)
}

fun CoroutineScope.produceNumbers() = produce<Int> {
    var x = 1
    while (true){
        send(x++)
    }
}

fun CoroutineScope.square(numbers : ReceiveChannel<Int>) : ReceiveChannel<Int> = produce {
    for (x in numbers) send(x * x)
}